前兩天我已經學會用 CC: Tweaked 電腦讀取磁片和播放音樂
今天我要來寫 Code 啦 !!!
.....
不是本來就在寫 Code 嗎?
但這次我要在麥塊世界裡的超大螢幕寫 Code ~
來看看新的 Monitor 方塊長怎樣?
.....
螢幕和電腦一比一相同大小,有點搞不清楚誰是誰 XD
這畫面上方是電腦主機,下方是螢幕
跟磁碟機一樣,螢幕可以接在電腦旁邊任何位置
而我在電腦主機輸入
monitor bottom ls
意思就是,執行 ls,但把輸出重新導向到下方螢幕
我目前的位置是新電腦的根目錄,所以螢幕上只顯示 rom
雖然在現實世界,不會真的幹這種事(要也是拿來看電影打電動啊,怎麼會拿寫 Code)
但至少,我可以在麥塊裡面實現囉!
我發現螢幕方塊是可以堆疊的,兩個相鄰的螢幕會自動合併成更大的螢幕!
比較可惜的是,我原本以為可以無限制堆疊(也太貪心)
但實測後得知,最多可以堆出 長8方塊、高6方塊的大螢幕
但以人物比例來看,應該是有 100 吋吧 XD
我在電腦上輸入
monitor top edit rom/programs/monitor.lua
就形成這個畫面啦!順便找一堆村民來看我寫 Code ...
接下來看看 monitor.lua 在做些什麼事
首先看到這一行很陌生
local monitor = peripheral.wrap(sName)
接著再看 /rom/apis/peripheral.lua
看到一個有趣的新東西 setmetatable
function wrap(name)
expect(1, name, "string")
local methods = peripheral.getMethods(name)
if not methods then
return nil
end
local result = setmetatable({}, {
__name = "peripheral",
name = name,
type = peripheral.getType(name),
})
for _, method in ipairs(methods) do
result[method] = function(...)
return peripheral.call(name, method, ...)
end
end
return result
end
在 Lua,每個 table 都可以自定義自己的 metatable 來改變預設的行為
預設情況下,metatable 是 nil
t = { 1, 2, 3 }
print(getmetatable(t)) -- nil
我們可以透過 setmetatable
來改變其預設的 metatable
不過在 Lua,只能改 table 的 metatable
其他型別的 metatable,據了解可以透過 C/C++ 修改
還記得之前我印出 table 時,都是得到記憶體位址嗎?
改變 metatable 定義後,我們可以直接印出 table 裡面所有值
t = { 1, 2, 3 }
print(getmetatable(t)) -- nil
print(t) -- table: 0x20e6b60
setmetatable(t, {
__tostring = function(table) -- 改變 table 被 print 的輸出
local str = ''
for _, value in pairs(table) do
str = str .. value .. ','
end
return str
end
})
print(t) -- 1,2,3,
以下是一些可以透過 metatable 改變的行為,稱為 metamethod
但應該不止這些,有些 metamethod 我沒有深入探究
operator | metamethod |
---|---|
+ | __add |
- | __sub |
* | __mul |
/ | __div |
- (負數) | __unm |
% | __mod |
^ (次方) | __pow |
== | __eq |
< | __lt |
<= | __le |
.. | __concat |
__name 可以改變預設的型別顯示,雖然我看不出用途...
__len 可以改變計算元素數量的方式
__pairs 可以改變 pairs, iparis 迭代函數取值的規則
__index 改變用 key index 取值的規則
__newindex 改變新增元素的規則
__tostring 改變 table 被 print 的輸出
以下是更多的範例
t1 = { 1, 2, 3 }
t2 = { 4, 5, 6 }
print(getmetatable(t1)) -- nil
print(t1) -- table: 0x23d87d0
mt = {
__name = "mytable",
__add = function(tableA, tableB)
local result = setmetatable({}, mt) -- 這邊要記得設定 metatable,這樣新的 table 也仍然是自定義行為
for i = 1, #tableA do
table.insert(result, tableA[i])
end
for i = 1, #tableB do
table.insert(result, tableB[i])
end
return result
end,
__index = function(table, key) -- 這樣這個 table 就變成存取從 0 index 開始
return table[key + 1]
end
}
setmetatable(t1, mt)
setmetatable(t2, mt)
print(t1) -- mytable: 0x23d87d0
mt.__tostring = function(table) -- mt["__tostring"] 的語法糖
local str = ''
for _, value in pairs(table) do
str = str .. value .. ','
end
return str
end
print(t1) -- 1,2,3,
print(t1 + t2) -- 1,2,3,4,5,6,
print(t1[0]) -- 1
metatable 可以做如上述這麼大幅度的行為改變
但 Lua 也提供我們方式可以保護 metatable
使用 setmetatable 設定 metatable 之後,就再也不能改變
t = { 1, 2, 3 }
mt = {
__tostring = function(table)
local str = ''
for _, value in pairs(table) do
str = str .. value .. ','
end
return str
end,
__metatable = "Access Denied" -- 可以給任意值
}
setmetatable(t, mt)
print(t) -- 1,2,3,
setmetatable(t, {}) -- input:15: cannot change a protected metatable
以上就是 Lua metatable 和 metamethod 的應用